﻿#region Copyright

// // The contents of this file are subject to the Mozilla Public License
// // Version 1.1 (the "License"); you may not use this file except in compliance
// // with the License. You may obtain a copy of the License at
// //   
// // http://www.mozilla.org/MPL/
// //   
// // Software distributed under the License is distributed on an "AS IS"
// // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// // License for the specific language governing rights and limitations under 
// // the License.
// //   
// // The Initial Developer of the Original Code is Robert Smyth.
// // Portions created by Robert Smyth are Copyright (C) 2008-2013.
// //   
// // All Rights Reserved.

#endregion

using System;
using NLog;
using NoeticTools.NWorkflow.DotNetInterop;
using NoeticTools.NWorkflow.Exceptions;
using NoeticTools.NWorkflow.ProgressMonitoring;


namespace NoeticTools.NWorkflow.Steps
{
    public class StepProgressMonitor : IProgress
    {
        private const double MinimumCompletedDelta = 0.0001;
        private readonly Logger _logger;
        private readonly IStepProgressListener _progressListener;
        private readonly IStep _step;
        private double _completed = double.NaN;
        private double _lastProgressTrigger = -2.0;
        private readonly IProgress _rulesProgress;

        public StepProgressMonitor(IProgress rulesProgress, IStepProgressListener progressListener, IStep step, bool progressAvailable, Logger logger)
        {
            _rulesProgress = rulesProgress;
            _progressListener = progressListener;
            _step = step;
            _logger = logger;
            ProgressAvailable = progressAvailable;
        }

        public double Completed
        {
            get { return _completed; }
            set
            {
                if (value < 0.0 || value > 1.0)
                {
                    throw new WorkflowException("Out of range value. Completed is a percentage ranging from 0.0 to 1.0.");
                }

                if (double.IsNaN(_completed) || Math.Abs(value - _completed) > MinimumCompletedDelta)
                {
                    _completed = value;
                    //Console.WriteLine("== step {0}, {1:P1} Completed", _step.Name, value);//>>>

                    _progressListener.OnProgress(_step.Name, this);

                    if (_completed - _lastProgressTrigger >= _step.OnProgressPercentage)
                    {
                        _lastProgressTrigger = _completed;

                        if (_step.OnProgressAction != null)
                        {
                            //_logger.Info("== On progress action fired");//>>>
                            _step.OnProgressAction();
                        }
                    }
                }
            }
        }

        public double StartingWeight { get { return _rulesProgress.StartingWeight; } set { _rulesProgress.StartingWeight = value; } }

        public bool ProgressAvailable { get; private set; }

        public string Message
        {
            get { return _step.Name; }
            set { }
        }

        public double AccumulatedCompleted
        {
            get { return StartingWeight + Completed*Total; }
        }

        public double Total { get { return _rulesProgress.Total; } set { _rulesProgress.Total = value; } }

        public virtual double UpdateWeights(double startingWeight)
        {
            StartingWeight = startingWeight;
            return StartingWeight + Total;
        }

        public IProgress Inner { get; set; }
    }
}